[IA64] enable acceleration of external interrupt
authorawilliam@xenbuild.aw <awilliam@xenbuild.aw>
Wed, 12 Jul 2006 19:20:15 +0000 (13:20 -0600)
committerawilliam@xenbuild.aw <awilliam@xenbuild.aw>
Wed, 12 Jul 2006 19:20:15 +0000 (13:20 -0600)
This patch is to enable acceleration of externel interrupt
which is described in VTI spec.

Signed-off-by: Anthony Xu <anthony.xu@intel.com>
xen/arch/ia64/vmx/pal_emul.c
xen/arch/ia64/vmx/vlsapic.c
xen/arch/ia64/vmx/vmx_init.c
xen/arch/ia64/vmx/vmx_process.c
xen/arch/ia64/vmx/vmx_virt.c
xen/include/asm-ia64/vmx_vcpu.h

index 8fcdf21bbc7fe5723c6766f37a991fc3799bf84e..4857dba00ab7b7b6f00b992a6917748fb92747a5 100644 (file)
@@ -146,7 +146,7 @@ static struct ia64_pal_retval
 pal_halt_light(VCPU *vcpu) {
        struct ia64_pal_retval result;
        
-       if (SPURIOUS_VECTOR == vmx_check_pending_irq(vcpu))
+       if (!is_unmasked_irq(vcpu))
                do_sched_op_compat(SCHEDOP_block, 0);
            
        INIT_PAL_STATUS_SUCCESS(result);
index 749607d8eb06504a37eb37f7f11277a23d93d3e8..3f105ce3128ec4761e468c62ab2d6333a9eae849 100644 (file)
@@ -289,7 +289,7 @@ static void update_vhpi(VCPU *vcpu, int vec)
         vhpi = 16;
     }
     else {
-        vhpi = vec / 16;
+        vhpi = vec >> 4;
     }
 
     VCPU(vcpu,vhpi) = vhpi;
@@ -436,7 +436,7 @@ static int highest_inservice_irq(VCPU *vcpu)
  */
 static int is_higher_irq(int pending, int inservice)
 {
-    return ( (pending >> 4) > (inservice>>4) || 
+    return ( (pending > inservice) || 
                 ((pending != NULL_VECTOR) && (inservice == NULL_VECTOR)) );
 }
 
@@ -460,7 +460,6 @@ static int
 _xirq_masked(VCPU *vcpu, int h_pending, int h_inservice)
 {
     tpr_t    vtpr;
-    uint64_t    mmi;
     
     vtpr.val = VCPU(vcpu, tpr);
 
@@ -474,9 +473,9 @@ _xirq_masked(VCPU *vcpu, int h_pending, int h_inservice)
     if ( h_inservice == ExtINT_VECTOR ) {
         return IRQ_MASKED_BY_INSVC;
     }
-    mmi = vtpr.mmi;
+
     if ( h_pending == ExtINT_VECTOR ) {
-        if ( mmi ) {
+        if ( vtpr.mmi ) {
             // mask all external IRQ
             return IRQ_MASKED_BY_VTPR;
         }
@@ -486,7 +485,7 @@ _xirq_masked(VCPU *vcpu, int h_pending, int h_inservice)
     }
 
     if ( is_higher_irq(h_pending, h_inservice) ) {
-        if ( !mmi && is_higher_class(h_pending, vtpr.mic) ) {
+        if ( is_higher_class(h_pending, vtpr.mic + (vtpr.mmi << 4)) ) {
             return IRQ_NO_MASKED;
         }
         else {
@@ -577,6 +576,8 @@ int vmx_check_pending_irq(VCPU *vcpu)
         isr = vpsr.val & IA64_PSR_RI;
         if ( !vpsr.ic )
             panic_domain(regs,"Interrupt when IC=0\n");
+        if (VCPU(vcpu, vhpi))
+            update_vhpi(vcpu, NULL_VECTOR);
         vmx_reflect_interruption(0,isr,0, 12, regs ); // EXT IRQ
     }
     else if ( mask == IRQ_MASKED_BY_INSVC ) {
@@ -612,6 +613,20 @@ void guest_write_eoi(VCPU *vcpu)
 //    vmx_check_pending_irq(vcpu);
 }
 
+int is_unmasked_irq(VCPU *vcpu)
+{
+    int h_pending, h_inservice;
+
+    h_pending = highest_pending_irq(vcpu);
+    h_inservice = highest_inservice_irq(vcpu);
+    if ( h_pending == NULL_VECTOR || 
+        irq_masked(vcpu, h_pending, h_inservice) != IRQ_NO_MASKED ) {
+        return 0;
+    }
+    else
+        return 1;
+}
+
 uint64_t guest_read_vivr(VCPU *vcpu)
 {
     int vec, h_inservice;
@@ -628,7 +643,8 @@ uint64_t guest_read_vivr(VCPU *vcpu)
  
     VLSAPIC_INSVC(vcpu,vec>>6) |= (1UL <<(vec&63));
     VCPU(vcpu, irr[vec>>6]) &= ~(1UL <<(vec&63));
-    update_vhpi(vcpu, NULL_VECTOR);     // clear VHPI till EOI or IRR write
+    if (VCPU(vcpu, vhpi))
+        update_vhpi(vcpu, NULL_VECTOR); // clear VHPI till EOI or IRR write
     local_irq_restore(spsr);
     return (uint64_t)vec;
 }
index 074c536f56c851b506daea782a3b592d2660bd95..8cd3501ed9e7de634b06eb624e4ada81b16b4b3d 100644 (file)
@@ -183,7 +183,8 @@ static vpd_t *alloc_vpd(void)
        mregs->vac.a_from_cpuid = 1;
        mregs->vac.a_cover = 1;
        mregs->vac.a_bsw = 1;
-
+       mregs->vac.a_int = 1;
+       
        mregs->vdc.d_vmsw = 1;
 
        return vpd;
index 857195942b6fa20ae53495d37a4f31bfdc839ec5..763c11d10b1d989fef5683a2e165e92fe5354da6 100644 (file)
@@ -35,7 +35,7 @@
 #include <asm/io.h>
 #include <asm/processor.h>
 #include <asm/desc.h>
-//#include <asm/ldt.h>
+#include <asm/vlsapic.h>
 #include <xen/irq.h>
 #include <xen/event.h>
 #include <asm/regionreg.h>
@@ -188,13 +188,13 @@ void leave_hypervisor_tail(struct pt_regs *regs)
     struct vcpu *v = current;
     // FIXME: Will this work properly if doing an RFI???
     if (!is_idle_domain(d) ) { // always comes from guest
-        extern void vmx_dorfirfi(void);
-        struct pt_regs *user_regs = vcpu_regs(current);
+//        struct pt_regs *user_regs = vcpu_regs(current);
+        local_irq_enable();
         do_softirq();
         local_irq_disable();
 
-        if (user_regs != regs)
-            printk("WARNING: checking pending interrupt in nested interrupt!!!\n");
+//        if (user_regs != regs)
+//            printk("WARNING: checking pending interrupt in nested interrupt!!!\n");
 
         /* VMX Domain N has other interrupt source, saying DM  */
         if (test_bit(ARCH_VMX_INTR_ASSIST, &v->arch.arch_vmx.flags))
@@ -215,12 +215,18 @@ void leave_hypervisor_tail(struct pt_regs *regs)
 
         if ( v->arch.irq_new_pending ) {
             v->arch.irq_new_pending = 0;
+            v->arch.irq_new_condition = 0;
             vmx_check_pending_irq(v);
+            return;
+        }
+        if (VCPU(v, vac).a_int) {
+            vhpi_detection(v);
+            return;
+        }
+        if (v->arch.irq_new_condition) {
+            v->arch.irq_new_condition = 0;
+            vhpi_detection(v);
         }
-//        if (VCPU(v,vac).a_bsw){
-//            save_banked_regs_to_vpd(v,regs);
-//        }
-
     }
 }
 
index c1fabd45ffba8115040ea51fb134664c2faeed21..08d6683f58aef5c3532bf6b1e533afd8a802d943 100644 (file)
@@ -30,7 +30,6 @@
 #include <asm/vmx.h>
 #include <asm/virt_event.h>
 #include <asm/vmx_phy_mode.h>
-extern void vhpi_detection(VCPU *vcpu);//temporarily place here,need a header file.
 
 void
 ia64_priv_decoder(IA64_SLOT_TYPE slot_type, INST64 inst, UINT64  * cause)
@@ -1342,14 +1341,6 @@ IA64FAULT vmx_emul_mov_from_cr(VCPU *vcpu, INST64 inst)
 }
 
 
-static void post_emulation_action(VCPU *vcpu)
-{
-    if ( vcpu->arch.irq_new_condition ) {
-        vcpu->arch.irq_new_condition = 0;
-        vhpi_detection(vcpu);
-    }
-}
-
 //#define  BYPASS_VMAL_OPCODE
 extern IA64_SLOT_TYPE  slot_types[0x20][3];
 IA64_BUNDLE __vmx_get_domain_bundle(u64 iip)
@@ -1552,8 +1543,6 @@ if ( (cause == 0xff && opcode == 0x1e000000000) || cause == 0 ) {
     }
 
     recover_if_physical_mode(vcpu);
-    post_emulation_action (vcpu);
-//TODO    set_irq_check(v);
     return;
 
 }
index 90eb33fd15265bb2c1b99dbabd4ba6ea204a2a8f..d77805d4d6b53e9087c3ef279e3b3625016eedf7 100644 (file)
@@ -103,6 +103,7 @@ extern void vtm_interruption_update(VCPU *vcpu, vtime_t* vtm);
 extern void vlsapic_reset(VCPU *vcpu);
 extern int vmx_check_pending_irq(VCPU *vcpu);
 extern void guest_write_eoi(VCPU *vcpu);
+extern int is_unmasked_irq(VCPU *vcpu);
 extern uint64_t guest_read_vivr(VCPU *vcpu);
 extern void vmx_inject_vhpi(VCPU *vcpu, u8 vec);
 extern int vmx_vcpu_pend_interrupt(VCPU *vcpu, uint8_t vector);